package com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qzsoft.jeemis.common.exception.RenException;
import com.qzsoft.zhjd.common.model.MarshallDataYjkj;
import com.qzsoft.zhjd.common.utils.AsphaltProtocolParserUtils;
import com.qzsoft.zhjd.common.utils.MarshallStabilityParserYjkjUtils;
import com.qzsoft.zhjd.common.utils.ParsedResult;
import com.qzsoft.zhjd.common.utils.ZhjdIotUtils;
import com.qzsoft.zhjd.laboratory.modules.asphaltPenetrometer.entity.AsphaltPenetrometerEntity;
import com.qzsoft.zhjd.laboratory.modules.asphaltPenetrometer.entity.AsphaltPenetrometerResEntity;
import com.qzsoft.zhjd.laboratory.modules.errorRecord.service.ErrorRecordService;
import com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.entity.MarshallStabilityNewEntity;
import com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.entity.MarshallStabilityNewProcessResEntity;
import com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.entity.MarshallStabilityNewResEntity;
import com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.mapper.MarshallStabilityNewResMapper;
import com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.service.MarshallStabilityNewProcessResService;
import com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.service.MarshallStabilityNewResService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qzsoft.zhjd.common.components.BaseServiceComponent;

import com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.mapper.MarshallStabilityNewMapper;
import com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.entity.MarshallStabilityNewEntity;
import com.qzsoft.zhjd.laboratory.modules.marshallStabilityNew.service.MarshallStabilityNewService;


@Service("marshallStabilityNewService")
public class MarshallStabilityNewServiceImpl extends ServiceImpl<MarshallStabilityNewMapper, MarshallStabilityNewEntity> implements MarshallStabilityNewService {

    @Autowired
    private MarshallStabilityNewMapper marshallStabilityNewMapper;

    @Autowired
    private MarshallStabilityNewResMapper resMapper;

    @Autowired
    private BaseServiceComponent baseServiceComponent;

    @Autowired
    private MarshallStabilityNewResService marshallStabilityNewResService;

    @Autowired
    private MarshallStabilityNewProcessResService marshallStabilityNewProcessResService;

    @Autowired
    private ErrorRecordService errorRecordService;

    private static Map<String,String> currentMap = new HashMap<>();

    /**
     * 列表
     */
    @Override
    public IPage<JSONObject> queryPage(Map<String, Object> params) {
        IPage<MarshallStabilityNewEntity> page = baseServiceComponent.getPage(params, MarshallStabilityNewEntity.class);
        return marshallStabilityNewMapper.queryPage(page,params);
    }

    /**
     * 信息
     * @return MarshallStabilityNewEntity
     */
    @Override
    public MarshallStabilityNewEntity getInfo(String id){
        return getById(id);
    }

    /**
     * 保存
     */
    @Override
    public void saveData(MarshallStabilityNewEntity marshallStabilityNew){
        save(marshallStabilityNew);
    }

    /**
     * 修改
     */
    @Override
    public void updateData(MarshallStabilityNewEntity marshallStabilityNew){
        updateById(marshallStabilityNew);
    }

    /**
     * 删除单条数据
     * @param id
     */
    @Override
    public void deleteOneData(String id){
        removeById(id);
    }

    /**
     * 删除
     */
    @Override
    public void deleteData(List<String> ids){
        removeByIds(ids);
    }

    /**
     *  解析马歇尔稳定度测定仪数据v2.X版本；
     * @param resData 试验结果数据
     * @param deviceId 试验设备id
     */
    @Override
    public void parsingData(String resData,String deviceId){
        try {
            //处理多个“FAFBFC”数据；
            List<String> resDatas = transfer(resData);
            for(String res : resDatas){
                parseLabData(res,deviceId);
            }

        } catch (Exception e) {
            errorRecordService.saveErrorData(ZhjdIotUtils.MARSHALL_STABILITY_NEW,deviceId,resData);
            throw new RenException("数据解析异常");
        }
    }

    //处理试验数据；
    private void parseLabData(String resData, String deviceId) {
        Date nowDate = new Date();
        List<String> dataList = ZhjdIotUtils.analyzeExperimentalData(resData);

        //如果数据以00开头，可能设备刚开机或重启，表示一次新的实验开始
        if(StringUtils.equals(dataList.get(0),"00")){
            currentMap.remove(deviceId);
        }
        //验证位不进行校验
        int i = 4;
        //试验数据
        if (StringUtils.equals(ZhjdIotUtils.DATA_TYPE_TEST, dataList.get(i))) {
            MarshallStabilityNewEntity entity = new MarshallStabilityNewEntity();
            entity.setDeviceId(deviceId);
            if(currentMap.get(deviceId) == null){
                MarshallStabilityNewResEntity resEntity = new MarshallStabilityNewResEntity();
                resEntity.setDeviceId(deviceId);
                marshallStabilityNewResService.save(resEntity);
                currentMap.put(deviceId,resEntity.getId());
            }
            //设置实验结果数据id
            entity.setResId(currentMap.get(deviceId));

            entity.setOriginalData(resData);
            entity.setCreateTime(nowDate);
            i++;
            entity.setFlag(dataList.get(i));

            // 将16进制转换为10进制数据，不含（0x）
            // 稳定度值WD，2字节无符号数，高位在前，2位小数。如2356，表示23.56KN
            i++;
//                String wd = "" + Integer.parseInt(dataList.get(i),16) + Integer.parseInt(dataList.get(i + 1),16);
            entity.setWd(ZhjdIotUtils.hexToTwoPoint(dataList.get(i)+dataList.get(i+1)));

            //流值FLUX，2字节无符号数，高位在前，2位小数。如367，表示3.67MM
            i += 2;
//                String flux = "" + Integer.parseInt(dataList.get(i),16) + Integer.parseInt(dataList.get(i + 1),16);
            entity.setFlux(ZhjdIotUtils.hexToTwoPoint(dataList.get(i)+dataList.get(i+1)));

            save(entity);
            //结果数据
        } else if (StringUtils.equals(ZhjdIotUtils.DATA_TYPE_RES, dataList.get(i))) {
            MarshallStabilityNewResEntity resEntity = new MarshallStabilityNewResEntity();
            resEntity.setId(currentMap.get(deviceId));
            currentMap.remove(deviceId);
            resEntity.setDeviceId(deviceId);
            resEntity.setOriginalData(resData);
            resEntity.setCreateTime(nowDate);

            // 将16进制转换为10进制数据，不含（0x）
            // 稳定度值WD，2字节无符号数，高位在前，2位小数。如2356，表示23.56KN
            i++;
//                String wd = "" + Integer.parseInt(dataList.get(i),16) + "." + Integer.parseInt(dataList.get(i + 1),16);
//                resEntity.setWd(ZhjdIotUtils.subByDecimalPlaces(2,wd));
            resEntity.setWd(ZhjdIotUtils.hexToTwoPoint(dataList.get(i)+dataList.get(i+1)));

//
            //流值FLUX，2字节无符号数，高位在前，2位小数。如367，表示3.67MM
            i += 2;
//                String flux = "" + Integer.parseInt(dataList.get(i),16) + "." + Integer.parseInt(dataList.get(i + 1),16);
//                resEntity.setFlux(ZhjdIotUtils.subByDecimalPlaces(2,flux));
            resEntity.setFlux(ZhjdIotUtils.hexToTwoPoint(dataList.get(i)+dataList.get(i+1)));
            marshallStabilityNewResService.saveOrUpdate(resEntity);
            //结果过程数据
        } else if (StringUtils.equals(ZhjdIotUtils.DATA_TYPE_PROCESS, dataList.get(i))) {
            MarshallStabilityNewProcessResEntity processEntity = new MarshallStabilityNewProcessResEntity();
            processEntity.setDeviceId(currentMap.get(deviceId));
            processEntity.setDeviceId(deviceId);
            processEntity.setOriginalData(resData);
            processEntity.setCreateTime(nowDate);
            marshallStabilityNewProcessResService.save(processEntity);
        }  else {
            throw new RenException("马歇尔稳定度数据解析异常：" + resData);
        }
    }

    //返回多个“FAFBFC...”数据List
    private List<String> transfer(String resData) {

        if(resData == null || !resData.contains("FAFBFC")){
            throw new RenException("马歇尔稳定度数据解析异常：" + resData);
        }
        //如果只有一个FAFBFC...数据，直接返回；
        if(resData.indexOf("FAFBFC") == resData.lastIndexOf("FAFBFC")){
            List<String> resDatas = new ArrayList<>();
            resDatas.add(resData);
            return resDatas;
        }
        //拼接第一个FAFBFC数据，有可能被截断，先查询上一条记录的原始数据，子表或主表
        //todo
        List<String> parts = new ArrayList<>();
        Pattern pattern = Pattern.compile("FAFBFC.*?(?=FAFBFC|$)", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(resData);

        while (matcher.find()) {
            parts.add(matcher.group());
        }
        return parts;
    }

    /**
     * 批处理历史数据,重新进行解析过程数据
     */
    public void reparseData(){
        //获取所有数据
        List<MarshallStabilityNewEntity> list = marshallStabilityNewMapper.selectList(new QueryWrapper<>());
        for(MarshallStabilityNewEntity item : list){
            List<String> dataList = ZhjdIotUtils.analyzeExperimentalData(item.getOriginalData());
            int i = 4;
            //试验数据
            MarshallStabilityNewEntity entity = item;
            i++;
            entity.setFlag(dataList.get(i));

            // 将16进制转换为10进制数据，不含（0x）
            // 稳定度值WD，2字节无符号数，高位在前，2位小数。如2356，表示23.56KN
            i++;
            String wd = "" + Integer.parseInt(dataList.get(i),16) + "." +Integer.parseInt(dataList.get(i + 1),16);
//            entity.setWd(ZhjdIotUtils.subByDecimalPlaces(2,wd));
            entity.setWd(new BigDecimal(wd));
            //流值FLUX，2字节无符号数，高位在前，2位小数。如367，表示3.67MM
            i += 2;
            String flux = "" + Integer.parseInt(dataList.get(i),16) + "." + Integer.parseInt(dataList.get(i + 1),16);
//            entity.setFlux(ZhjdIotUtils.subByDecimalPlaces(2,flux));
            entity.setFlux(new BigDecimal(flux));
            updateById(entity);
        }
    }

    /**
     * 绑定材料
     * @param marshallStabilityNewRes
     */
    public void changeSample(MarshallStabilityNewResEntity marshallStabilityNewRes){
        //更新试验结果表
        marshallStabilityNewResService.updateById(marshallStabilityNewRes);
        //查询试验过程数据
        List<MarshallStabilityNewEntity> processList = list(new LambdaQueryWrapper<MarshallStabilityNewEntity>().eq(MarshallStabilityNewEntity::getResId,marshallStabilityNewRes.getId()));
        if(CollectionUtil.isNotEmpty(processList)){
            for(MarshallStabilityNewEntity item : processList){
                item.setSampleId(marshallStabilityNewRes.getSampleId());
            }
            updateBatchById(processList);
        }
    }

    /**
     * 重新处理马歇尔试验历史数据；航天科宇v2.X版；
     * 1、解析结果数据；
     * 2、解析过程数据；
     * @param deviceId
     */
    @Override
    public void reParsingData(String deviceId) {
        //解析结果数据；
        if(StringUtils.isBlank(deviceId)){
            return;
        }
        LambdaQueryWrapper<MarshallStabilityNewResEntity> reWrapper = new LambdaQueryWrapper<>();
        reWrapper.eq(MarshallStabilityNewResEntity::getDeviceId,deviceId);
        reWrapper.isNotNull(MarshallStabilityNewResEntity::getOriginalData);
        List<MarshallStabilityNewResEntity> resEntities = resMapper.selectList(reWrapper);
        if(CollUtil.isEmpty(resEntities)){
            return;
        }
        for(MarshallStabilityNewResEntity resEntity:resEntities){
            String originalData = resEntity.getOriginalData();
            List<String> dataList = ZhjdIotUtils.analyzeExperimentalData(originalData);
            int i = 5;
            //稳定度
            resEntity.setWd(ZhjdIotUtils.hexToTwoPoint(dataList.get(i)+dataList.get(i+1)));
            //流值FLUX，2字节无符号数，高位在前，2位小数。如367，表示3.67MM
            i += 2;
            resEntity.setFlux(ZhjdIotUtils.hexToTwoPoint(dataList.get(i)+dataList.get(i+1)));
            resMapper.updateById(resEntity);
        }
        //解析过程数据；
        Set<String> resIds = resEntities.stream().map(MarshallStabilityNewResEntity::getId).collect(Collectors.toSet());
        LambdaQueryWrapper<MarshallStabilityNewEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(MarshallStabilityNewEntity::getResId,resIds);
        wrapper.eq(MarshallStabilityNewEntity::getFlag,"01");
        wrapper.isNotNull(MarshallStabilityNewEntity::getOriginalData);
        List<MarshallStabilityNewEntity> entities = baseMapper.selectList(wrapper);
        if(CollUtil.isEmpty(entities)){
            return;
        }
        for(MarshallStabilityNewEntity entity:entities){
            String originalData = entity.getOriginalData();
            List<String> dataList = ZhjdIotUtils.analyzeExperimentalData(originalData);
            int i = 5;
            entity.setWd(ZhjdIotUtils.hexToTwoPoint(dataList.get(i)+dataList.get(i+1)));
            i+=2;
            entity.setFlux(ZhjdIotUtils.hexToTwoPoint(dataList.get(i)+dataList.get((i+2))));
            baseMapper.updateById(entity);
        }


    }

    /**
     * 沥青混合料马歇尔稳定度试验仪 -- 北京中科建仪电子科技有限公司
     * @param resData
     * @param deviceId
     */
    @Override
    public void parsingDataMarshallBjzkjydz(String resData, String deviceId) {
        System.out.println("北京中科建仪电子科技有限公司沥青混合料马歇尔稳定度试验仪resData------->>>>>>"+resData);
        System.out.println("deviceId------->>>>>>"+deviceId);
        String deviceType = "MARSHALL_BJZKJYDZ";
        if(StringUtils.isNotBlank(deviceId)){
            ParsedResult parsedResult = AsphaltProtocolParserUtils.parseHexString(resData, deviceType);
            System.out.println("parsedResult------->>>>>>" + JSON.toJSONString(parsedResult));
            if(parsedResult != null){
                //试验数据
                System.out.println("parsedResult.getDataType()------->>>>>>" + parsedResult.getDataType());
                if(parsedResult.getDataType() == AsphaltProtocolParserUtils.TYPE_REALTIME){
                    MarshallStabilityNewEntity entity = new MarshallStabilityNewEntity();
                    entity.setDeviceId(deviceId);
                    entity.setOriginalData(resData);
                    entity.setFlux(parsedResult.getDtOrDf().divide(new BigDecimal(100)));
                    entity.setWd(parsedResult.getDpOrDs().divide(new BigDecimal(100)));
                    entity.setCreateTime(new Date());
                    if(parsedResult.getFlag() >= 0){
                        entity.setFlag(parsedResult.getFlag() == 1 ? "01" : "00");
                    }
                    System.out.println("AsphaltPenetrometerEntity------->>>>>>" + JSON.toJSONString(entity));
                    marshallStabilityNewMapper.insert(entity);
                }else if(parsedResult.getDataType() == AsphaltProtocolParserUtils.TYPE_RESULT){
                    //结果数据
                    MarshallStabilityNewResEntity entity = new MarshallStabilityNewResEntity();
                    entity.setDeviceId(deviceId);
                    entity.setOriginalData(resData);
                    entity.setFlux(parsedResult.getDtOrDf().divide(new BigDecimal(100)));
                    entity.setWd(parsedResult.getDpOrDs().divide(new BigDecimal(100)));
                    entity.setCreateTime(new Date());
                    System.out.println("AsphaltPenetrometerResEntity------->>>>>>" + JSON.toJSONString(entity));
                    resMapper.insert(entity);
                    LambdaUpdateWrapper<MarshallStabilityNewEntity> asphaltPenetrometerEntityLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                    asphaltPenetrometerEntityLambdaUpdateWrapper.eq(MarshallStabilityNewEntity::getDeviceId, deviceId);
                    asphaltPenetrometerEntityLambdaUpdateWrapper.set(MarshallStabilityNewEntity::getResId, entity.getId());
                    marshallStabilityNewMapper.update(null,asphaltPenetrometerEntityLambdaUpdateWrapper);
                }
            }
        }
    }

    /**
     * 云检科技 - 马歇尔稳定度试验仪
     */
    @Override
    public void parsingDataMarshallYjkj(String resData, String deviceId) {
        System.out.println("云检科技 - 马歇尔稳定度试验仪resData------->>>>>>"+resData);
        if(StringUtils.isNotBlank(deviceId)){
            MarshallDataYjkj parsedResult = MarshallStabilityParserYjkjUtils.parse(resData);
            if(parsedResult != null){
                //试验数据
                if(parsedResult.getDataType() == MarshallStabilityParserYjkjUtils.DATA_TYPE_REAL_TIME){
                    MarshallStabilityNewEntity entity = new MarshallStabilityNewEntity();
                    entity.setDeviceId(deviceId);
                    entity.setOriginalData(resData);
                    entity.setFlux(new BigDecimal(parsedResult.getFlow()).setScale(2, RoundingMode.HALF_UP));
                    entity.setWd(new BigDecimal(parsedResult.getStability()).setScale(2, RoundingMode.HALF_UP));
                    entity.setCreateTime(new Date());
                    if(parsedResult.getFlag() >= 0){
                        entity.setFlag(parsedResult.getFlag() == 1 ? "01" : "00");
                    }
                    System.out.println("AsphaltPenetrometerEntity------->>>>>>" + JSON.toJSONString(entity));
                    marshallStabilityNewMapper.insert(entity);
                }else if(parsedResult.getDataType() == MarshallStabilityParserYjkjUtils.DATA_TYPE_FINAL_RESULT){
                    //结果数据
                    MarshallStabilityNewResEntity entity = new MarshallStabilityNewResEntity();
                    entity.setDeviceId(deviceId);
                    entity.setOriginalData(resData);
                    entity.setFlux(new BigDecimal(parsedResult.getFlow()).setScale(2, RoundingMode.HALF_UP));
                    entity.setWd(new BigDecimal(parsedResult.getStability()).setScale(1, RoundingMode.HALF_UP));
                    entity.setCreateTime(new Date());
                    System.out.println("AsphaltPenetrometerResEntity------->>>>>>" + JSON.toJSONString(entity));
                    resMapper.insert(entity);
                    LambdaUpdateWrapper<MarshallStabilityNewEntity> asphaltPenetrometerEntityLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                    asphaltPenetrometerEntityLambdaUpdateWrapper.eq(MarshallStabilityNewEntity::getDeviceId, deviceId);
                    asphaltPenetrometerEntityLambdaUpdateWrapper.set(MarshallStabilityNewEntity::getResId, entity.getId());
                    marshallStabilityNewMapper.update(null,asphaltPenetrometerEntityLambdaUpdateWrapper);
                }
            }
        }
    }
}
